﻿using System.Runtime.CompilerServices;
using Dyao.Book.Contract;

namespace Dyao.Book.Application
{

    /// <summary>
    /// 任务中心执行上下文接口
    /// </summary>
    public interface ITaskCenterContext : ITaskCenterExtend
    {
        /// <summary>
        /// 服务提供
        /// </summary>
        IServiceProvider ServiceProvider { get; }

        TaskCenterDto TaskModel { get; }

        /// <summary>
        /// 获取任务中心请求的参数
        /// </summary>
        /// <returns></returns>
        Task<string> GetRequestParametersStringAsync();
    }

    public interface ITaskCenterExtend
    {
        void Set(object key, object value);

        object Get(object key);

        bool IsExists(object key);

        bool TryGetValue<T>(object key, out T value);

        bool Remove(object key);

        void Clear();
    }

    public class TaskCenterExtend : ITaskCenterExtend
    {
        private static IReadOnlyCollection<object> _emptyKeys = new object[0];

        public TaskCenterExtend()
        {
        }

        public TaskCenterExtend(IDictionary<object, object> dict)
        {
            Extensions = dict;
        }

        protected IDictionary<object, object> Extensions { get; set; }

        /// <summary>
        /// 扩展字典是否已实例化
        /// </summary>
        protected bool IsExtCreated => Extensions != null;

        protected virtual IDictionary<object, object> CloneExtension()
        {
            IDictionary<object, object> dict = null;

            if (this.Extensions != null)
            {
                dict = new Dictionary<object, object>();

                foreach (var kv in this.Extensions)
                {
                    object value = kv.Value is ICloneable cl ? cl.Clone() : kv.Value;

                    dict[kv.Key] = value;
                }
            }

            return dict;
        }


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected void ExtSet(object key, object value)
        {
            if (Extensions == null)
            {
                Extensions = new Dictionary<object, object>();
            }

            Extensions[key] = value;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected object ExtGet(object key)
        {
            ExtTryGetValue(key, out object value);

            return value;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected bool IsExtExists(object key)
        {
            return IsExtCreated && Extensions.ContainsKey(key);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected bool ExtRemove(object key)
        {
            if (IsExtCreated)
            {
                return Extensions.Remove(key);
            }

            return false;
        }

        protected IReadOnlyCollection<object> GetExtKeys()
        {
            if (IsExtCreated)
            {
                if (Extensions is Dictionary<object, object> dict)
                {
                    return dict.Keys;
                }

                return Extensions.Keys.ToArray();
            }

            return _emptyKeys;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected bool ExtTryGetValue<T>(object key, out T value)
        {
            value = default;
            if (IsExtCreated && Extensions.TryGetValue(key, out object objectValue))
            {
                if (objectValue != null)
                {
                    value = (T)objectValue;
                }

                return true;
            }

            return false;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected void ExtClear()
        {
            if (IsExtCreated)
            {
                Extensions.Clear();
            }
        }

        #region // ITaskCenterExtend 实现

        object ITaskCenterExtend.Get(object key)
        {
            return ExtGet(key);
        }

        bool ITaskCenterExtend.IsExists(object key)
        {
            return IsExtExists(key);
        }

        void ITaskCenterExtend.Set(object key, object value)
        {
            ExtSet(key, value);
        }

        bool ITaskCenterExtend.TryGetValue<T>(object key, out T value)
        {
            return ExtTryGetValue(key, out value);
        }

        bool ITaskCenterExtend.Remove(object key)
        {
            return ExtRemove(key);
        }

        void ITaskCenterExtend.Clear()
        {
            ExtClear();
        }

        #endregion //end ITaskCenterExtend
    }
}